home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1990, 1991 by Michael Davidson.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software
- * and its documentation for any purpose and without fee is hereby
- * granted, provided that the above copyright notice appear in all
- * copies and that both that copyright notice and this permission
- * notice appear in supporting documentation.
- *
- * This software is provided "as is" without express or implied warranty.
- */
-
- /*
- * svga.c - support routines for SVGA cards
- */
-
- #include <stdlib.h>
- #include "video.h"
- #include "vdev.h"
- #include "v86types.h"
- #include "vbios.h"
- #include "svga.h"
-
- struct svga_mode_info *SVGAModeTable;
- struct svga_mode_info *SVGAModeInfo;
- int SVGAMaxModeIndex;
-
- static int svga_bios_initial_mode = -1;
- /*
- * svga_reset()
- */
- static void
- svga_reset()
- {
- if (svga_bios_initial_mode != -1)
- VBiosSetMode(svga_bios_initial_mode);
- }
-
- /*
- * svga_setmode()
- */
- static int
- svga_setmode(
- int i
- )
- {
- struct svga_mode_info *s;
-
- if (i < 0 || i > SVGAMaxModeIndex)
- return -1;
-
- s = &SVGAModeTable[i];
-
- VBiosSetMode(s->bios_mode | 0x80);
- if ((VBiosGetMode() & 0x7f) != s->bios_mode)
- return -1;
-
- if (s->attributes & SVGA_TEXT_MODE) /* text mode */
- {
- VBiosDisableBlink();
- VBiosSetCursorPosition(s->width, s->height);
- }
-
- /*
- * make sure start address is 0
- */
- outw(0x3d4, 0x000c);
- outw(0x3d4, 0x000d);
-
- if (s->attributes & SVGA_GRAPHICS_MODE)
- {
- switch (s->depth)
- {
- case 15:
- case 16:
- case 24:
- RGB32Shift[0] = s->red_shift;
- RGB32Shift[1] = s->green_shift;
- RGB32Shift[2] = s->blue_shift;
- RGB32Bits[0] = s->red_bits;
- RGB32Bits[1] = s->green_bits;
- RGB32Bits[2] = s->blue_bits;
- break;
-
- default:
- break;
- }
- }
-
- SVGAModeInfo = s;
- return 0;
- }
-
- svga_mode_supported(
- int mode
- )
- {
- VBiosSetMode(mode | 0x80);
- return (VBiosGetMode() & 0x7f) == mode;
- }
-
- /*
- * svga_setpalette()
- */
- static void
- svga_setpalette(
- color_t *colormap,
- int ncolors
- )
- {
- int i;
-
- inb(0x3da);
- for (i = 0; i < 16; i++)
- {
- outb(0x3c0, i);
- outb(0x3c0, i);
- }
-
- inb(0x3da);
- outb(0x3c8, 0);
- while (--ncolors >= 0)
- {
- outb(0x3c9, RGB8Lookup[0][colormap->red] >> 2);
- outb(0x3c9, RGB8Lookup[1][colormap->green] >> 2);
- outb(0x3c9, RGB8Lookup[2][colormap->blue] >> 2);
- colormap++;
- }
- outb(0x3c0, 0x20);
- }
-
- static void
- svga_putpixels8(
- int x,
- int y,
- unsigned char *pixels,
- int npixels
- )
- {
- struct svga_mode_info *s = SVGAModeInfo;
- int bank;
- long offset;
-
- offset = y * s->scanline_length + x;
-
- if (s->window_size > 0)
- {
- bank = offset / s->window_size;
- offset %= s->window_size;
- bank *= (s->window_size / s->window_granularity);
-
- (*s->window_control)(bank);
-
- while (offset + npixels > s->window_size)
- {
- int n;
-
- n = s->window_size - offset;
- memcpy(s->window_address + offset, pixels, n);
- offset = 0;
- pixels += n;
- npixels -= n;
- bank += (s->window_size / s->window_granularity);
- (*s->window_control)(bank);
- }
- }
-
- memcpy(s->window_address + offset, pixels, npixels);
- }
-
- static void
- svga_putpixels24(
- int x,
- int y,
- unsigned char *pixels,
- int npixels
- )
- {
- switch (SVGAModeInfo->depth)
- {
- case 8:
- svga_putpixels24to8(x, y, pixels, npixels);
- break;
-
- case 15:
- case 16:
- svga_putpixels24to16(x, y, pixels, npixels);
- break;
-
- case 24:
- svga_putpixels24to24(x, y, pixels, npixels);
- break;
- }
- }
-
- svga_putpixels24to8(
- int x,
- int y,
- unsigned char *pixels,
- int npixels
- )
- {
- struct svga_mode_info *s = SVGAModeInfo;
- int bank;
- long offset;
-
- offset = y * s->scanline_length + x;
-
- if (s->window_size > 0)
- {
- bank = offset / s->window_size;
- offset %= s->window_size;
- bank *= (s->window_size / s->window_granularity);
-
- (*s->window_control)(bank);
-
- while (offset + npixels > s->window_size)
- {
- int n;
-
- n = s->window_size - offset;
- CopyPixels24to8(pixels, s->window_address + offset, n, VPixelLookup);
- offset = 0;
- pixels += n * 3;
- npixels -= n;
- bank += (s->window_size / s->window_granularity);
- (*s->window_control)(bank);
- }
- }
-
- CopyPixels24to8(pixels, s->window_address + offset, npixels, VPixelLookup);
- }
-
- svga_putpixels24to16(
- int x,
- int y,
- unsigned char *pixels,
- int npixels
- )
- {
- struct svga_mode_info *s = SVGAModeInfo;
- int bank;
- long offset;
-
- offset = (y * s->scanline_length) + (x * 2);
-
- if (s->window_size > 0)
- {
- bank = offset / s->window_size;
- offset %= s->window_size;
- bank *= (s->window_size / s->window_granularity);
-
- (*s->window_control)(bank);
-
- while (offset + npixels*2 > s->window_size)
- {
- int n;
-
- n = (s->window_size - offset) / 2;
- GammaCopyPixels24to16(pixels, s->window_address + offset, n);
- offset = 0;
- pixels += n * 3;
- npixels -= n;
- bank += (s->window_size / s->window_granularity);
- (*s->window_control)(bank);
- }
- }
- GammaCopyPixels24to16(pixels, s->window_address + offset, npixels);
- }
-
- svga_putpixels24to24(
- int x,
- int y,
- unsigned char *pixels,
- int npixels
- )
- {
- struct svga_mode_info *s = SVGAModeInfo;
- int bank;
- long offset;
- int n;
-
- offset = (y * s->scanline_length) + (x * 3);
-
- if (s->window_size > 0)
- {
- bank = offset / s->window_size;
- offset %= s->window_size;
- bank *= (s->window_size / s->window_granularity);
-
- (*s->window_control)(bank);
-
- if (offset + npixels*3 >= s->window_size)
- {
- extern void *alloca(int);
- unsigned char *tmp = alloca(npixels * 3);
-
- GammaCopyPixels24to24(pixels, tmp, npixels);
- n = s->window_size - offset;
- memcpy(s->window_address + offset, tmp, n);
- tmp += n;
- n = (npixels * 3) - n;
- bank += (s->window_size / s->window_granularity);
- (*s->window_control)(bank);
- memcpy(s->window_address, tmp, n);
- }
- else
- {
- GammaCopyPixels24to24(pixels, s->window_address + offset, npixels);
- }
- }
- else
- {
- GammaCopyPixels24to24(pixels, s->window_address + offset, npixels);
- }
- }
-
- /*
- * svga_puttext()
- */
- static void
- svga_puttext(
- int x,
- int y,
- register byte_t *buf,
- int nbytes
- )
- {
- struct svga_mode_info *s = SVGAModeInfo;
-
- memcpy(s->window_address + (y * s->scanline_length) + (x * 2), buf, nbytes);
- }
-
- static void
- svga_clear(
- int bg
- )
- {
- struct svga_mode_info *s = SVGAModeInfo;
-
- long nbytes;
-
- nbytes = s->scanline_length * s->height;
-
- if (s->attributes & SVGA_TEXT_MODE) /* text mode */
- {
- memset(s->window_address, bg | (bg << 4), nbytes);
- }
- else
- {
- int bank;
- int step;
-
- step = (s->window_size / s->window_granularity);
-
-
- if (s->window_size > 0)
- {
- long n;
- for (bank = 0; nbytes > 0; bank += step)
- {
- (*s->window_control)(bank);
- n = nbytes > s->window_size ? s->window_size : nbytes;
- memset(s->window_address, bg, n);
- nbytes -= n;
- }
- }
- else
- memset(s->window_address, bg, nbytes);
-
- }
- }
-
- /*
- * svga_setup() - common setup code called by card-specific init routines
- */
- int
- svga_setup(
- struct vdev *v,
- struct svga_mode_info *svga_modes,
- void (*win_ctl)()
- )
- {
- int i;
- struct svga_mode_info *s;
- vmode_t *m;
-
- /*
- * set up default values for anything not explicitly initialised already
- */
- SVGAMaxModeIndex = 0;
- SVGAModeTable = svga_modes;
-
-
- for (s = svga_modes; s->attributes != 0; s++)
- {
- SVGAMaxModeIndex++;
-
- if (s->scanline_length == 0)
- {
- int n;
-
- n = (s->attributes & SVGA_TEXT_MODE) ? 2 : ((s->depth + 7) / 8);
- s->scanline_length = s->width * n;
- }
-
- if (s->window_address == 0)
- {
- if (s->attributes & SVGA_TEXT_MODE)
- s->window_address = (void *) 0xB8000;
- else
- s->window_address = (void *) 0xA0000;
- }
-
- if (s->window_size == 0)
- s->window_size = 0x10000;
-
- if (s->window_granularity == 0)
- s->window_granularity = s->window_size;
-
- if (s->window_control == 0)
- s->window_control = win_ctl;
-
- if (s->depth > 8 && (s->red_bits | s->green_bits | s->blue_bits) == 0)
- {
- switch (s->depth)
- {
- case 15:
- s->red_bits = 5;
- s->green_bits = 5;
- s->blue_bits = 5;
- s->red_shift = 10;
- s->green_shift = 5;
- s->blue_shift = 0;
- break;
-
- case 16:
- s->red_bits = 5;
- s->green_bits = 6;
- s->blue_bits = 5;
- s->red_shift = 11;
- s->green_shift = 5;
- s->blue_shift = 0;
- break;
-
- case 24:
- s->red_bits = 8;
- s->green_bits = 8;
- s->blue_bits = 8;
- s->red_shift = 16;
- s->green_shift = 8;
- s->blue_shift = 0;
- break;
- }
- }
- }
-
- m = (vmode_t *) malloc(sizeof(vmode_t) * (SVGAMaxModeIndex + 1));
- if (m == 0)
- fatal(0, "can't allocate memory for mode table");
-
- v->v_modes = m;
- s = svga_modes;
- for (i = 0; i <= SVGAMaxModeIndex; i++, m++, s++)
- {
- m->width = s->width;
- m->height = s->height;
- m->depth = s->depth;
- m->flags = 0;
- if (s->attributes & SVGA_MODE_SUPPORTED)
- m->flags |= V_MODE_SUPPORTED;
- if (s->attributes & SVGA_TEXT_MODE)
- m->flags |= V_TEXT_MODE;
- if (s->attributes & SVGA_GRAPHICS_MODE)
- m->flags |= V_GRAPHICS_MODE;
- }
-
- v->v_reset = svga_reset;
- v->v_setmode = svga_setmode;
- v->v_setpalette = svga_setpalette;
- v->v_clear = svga_clear;
- v->v_putpixels8 = svga_putpixels8;
- v->v_putpixels24 = svga_putpixels24;
- v->v_puttext = svga_puttext;
-
- svga_bios_initial_mode = VBiosGetMode();
-
- return 0;
- }
-